package com.cysyz.mylib.io.filesavetool.impl;

import com.cysyz.mylib.io.dirgenerator.IDirGenerator;
import com.cysyz.mylib.io.dirgenerator.impl.DateStyleDirGenerator;
import com.cysyz.mylib.io.filenamegenerator.IFileNameGenerator;
import com.cysyz.mylib.io.filenamegenerator.impl.FileNameGeneratorTimeStamp;
import com.cysyz.mylib.io.filesavetool.IFileSaveTool;
import com.cysyz.mylib.io.filesavetool.ISaveFileToRemoteTool;
import com.cysyz.mylib.io.realpathgenerator.IRealPathGenerator;
import com.cysyz.mylib.io.realpathgenerator.impl.SimpleRealPathGenerator;
import org.springframework.util.FileCopyUtils;

import java.io.File;
import java.io.IOException;

/**
 * @ClassName: FileSaveToolImpl
 * @Description: 文件保存工具,
 * 最终文件的保存路径是 absoluteSaveDirPrefixPath+ saveDir(保存文件方法中的参数) +
 * 					dirGenerator生成的目录(例如日期类型/2015/07/04/) + fileNameGenerator生成的名称(例如UUID, 时间戳.),
 * 					最终还可以使用realPathGenerator来对前面生成的路径进行修改.
 * @author 崔勇	cysyz1229@gmail.com
 * @date 2014-2-17 上午11:02:35
 */
public class FileSaveToolImpl implements IFileSaveTool {
	private String absoluteSaveDirPrefixPath;
	private IDirGenerator dirGenerator;
	private IFileNameGenerator fileNameGenerator;
    IRealPathGenerator realPathGenerator;

	private String urlPathPrefix;
	/**
	 *
	 * @param absoluteSaveDirPrefixPath 文件保存的完整路径前缀
	 */
	public FileSaveToolImpl(String absoluteSaveDirPrefixPath, String urlPathPrefix) {
		this(	absoluteSaveDirPrefixPath,
				urlPathPrefix,
				new DateStyleDirGenerator(),
				new FileNameGeneratorTimeStamp(),
				new SimpleRealPathGenerator());
	}

	public FileSaveToolImpl(String absoluteSaveDirPrefixPath, String urlPathPrefix, IDirGenerator dirGenerator, IFileNameGenerator fileNameGenerator, IRealPathGenerator realPathGenerator) {
		this.absoluteSaveDirPrefixPath = absoluteSaveDirPrefixPath;
		this.urlPathPrefix = urlPathPrefix;
		this.dirGenerator = dirGenerator;
        this.fileNameGenerator = fileNameGenerator;
        this.realPathGenerator = realPathGenerator;
    }

	/** @Title: saveFile
	 * @Description:
	 * @Author: 崔勇	cysyz1229@gmail.com
	 * @Version: V1.00
	 * @Date 2014-2-17 上午11:28:00
	 * @param srcBytes 要保存的文件
	 * @param srcFileName   要保存的文件名称，像web中文件上传时，srcFile只是一个服务端接受来自客户端的文件后生成的临时文件，并不是客户端上传时的那个文件。因此客户端的文件名称需要另外提供
	 * @param saveDir 文件的保存目录
	 * @return 文件保存的逻辑路径
	 */
	@Override
	public FileSavePathAndLogicPath saveFile(byte[] srcBytes, String srcFileName, String saveDir) throws IOException {

		return this.saveFile0(null, srcBytes, srcFileName, saveDir);
	}

	@Override
	public FileSavePathAndLogicPath saveFile(byte[] srcBytes, String srcFileName) throws IOException {

		return this.saveFile0(null, srcBytes, srcFileName, "");
	}

	@Override
	public FileSavePathAndLogicPath saveFile(byte[] srcBytes) throws IOException {

		return this.saveFile0(null, srcBytes, "", "");
	}

    /** @Title: saveFile
	 * @Description:
	 * @Author: 崔勇	cysyz1229@gmail.com
	 * @Version: V1.00
	 * @Date 2014-2-17 上午11:28:00
	 * @param srcFile 要保存的文件
	 * @param srcFileName   要保存的文件名称，像web中文件上传时，srcFile只是一个服务端接受来自客户端的文件后生成的临时文件，并不是客户端上传时的那个文件。因此客户端的文件名称需要另外提供
	 * @param saveDir 文件的保存目录
	 * @return 文件保存的逻辑路径
	 */
	public FileSavePathAndLogicPath saveFile(File srcFile, String srcFileName, String saveDir) throws IOException {

		return this.saveFile0(srcFile, null, srcFileName, saveDir);
	}

	private FileSavePathAndLogicPath saveFile0(File srcFile, byte[] srcBytes, String srcFileName, String saveDir) throws IOException {
		File destFile = populateRealSavePath(srcFileName, saveDir);

		if (srcFile != null) {
			FileCopyUtils.copy(srcFile, destFile);
		} else if (srcBytes != null) {
			FileCopyUtils.copy(srcBytes, destFile);
		}
		//srcFile.renameTo(destFile);

		StringBuilder fullLogicDestPathBuilder = populateFullLogicPath(destFile, saveDir);

		return new FileSavePathAndLogicPath(destFile, fullLogicDestPathBuilder.toString().replaceAll("[//]+", "/"));
	}

	private StringBuilder populateFullLogicPath(File destFile, String saveDir) {
		StringBuilder fullLogicDestPathBuilder = new StringBuilder("/");
		fullLogicDestPathBuilder.append(urlPathPrefix);
		fullLogicDestPathBuilder.append("/").append(saveDir);
		fullLogicDestPathBuilder.append(dirGenerator.generate());
		realPathGenerator.getRealPath(fullLogicDestPathBuilder);
		fullLogicDestPathBuilder.append("/").append(destFile.getName());
		return fullLogicDestPathBuilder;
	}

	@Override
	public String getRealSavePath(String logicPath, String fileSaveDir) {
		StringBuilder builder = new StringBuilder(this.absoluteSaveDirPrefixPath);
		builder.append("/").append(fileSaveDir);
		builder.append("/").append(logicPath.substring(urlPathPrefix.length()));
		return builder.toString().replaceAll("[/]+", "/");
	}

	public String getLogicPath(String realSavePath) {
		return null;
	}

	private File populateRealSavePath(String srcFileName, String saveDir) {
		StringBuilder fileSavePathBuilder = new StringBuilder(absoluteSaveDirPrefixPath);
		fileSavePathBuilder.append("/").append(saveDir);
		String middleDir = dirGenerator.generate();
		fileSavePathBuilder.append("/").append(middleDir);

		realPathGenerator.getRealPath(fileSavePathBuilder);
		//目标目录
		File destDir = new File(fileSavePathBuilder.toString());
		if (!destDir.exists()) {
			destDir.mkdirs();
		}

		String saveFileName = fileNameGenerator.generate(srcFileName);
		return new File(destDir, saveFileName);
	}

	/** @Title: saveFile
	 * @Description: TODO
	 * @Author: 崔勇	cysyz1229@gmail.com
	 * @Version: V1.00
	 * @Date 2014-2-17 上午11:28:00
	 * @param srcFileBytes
	 * @param srcFileName
	 * @param saveBaseURL
	 * @param saveDir
	 * @param saveFileToRemoteTool
	 * @return
	 */
	public String saveFile(byte[] srcFileBytes, String srcFileName,
			String saveBaseURL, String saveDir,
			ISaveFileToRemoteTool saveFileToRemoteTool) {

		return saveFile0(srcFileBytes, srcFileName, saveBaseURL, saveDir, null,
				saveFileToRemoteTool);
	}

	/**
	 * @Title: saveFile0
	 * @Description: TODO
	 * @Author: 崔勇	cysyz1229@gmail.com
	 * @Version: V1.00
	 * @Date 2014-2-17 上午11:03:52
	 * @param srcFileBytes 文件字节
	 * @param srcFileName  要保存的文件的名字
	 * @param saveBaseURL 要保存到的目的地的URL地址
	 * @param saveDir 要把文件保存到的目标URL地址的某个目录
	 * @param suffix 文件的后缀
	 * @param saveFileToRemoteTool 
	 * @return
	 */
	private String saveFile0(byte[] srcFileBytes, String srcFileName,
			String saveBaseURL, String saveDir,
			String suffix,
			ISaveFileToRemoteTool saveFileToRemoteTool) {
		String middlePath = dirGenerator.generate(srcFileName,
                saveBaseURL);
		String saveFileName = fileNameGenerator.generate(srcFileName);

		StringBuilder logicTargetPath = new StringBuilder(saveDir == null ? ""
				: saveDir);
		logicTargetPath.append("/");
		logicTargetPath.append(middlePath);
		logicTargetPath.append("/");
		logicTargetPath.append(saveFileName);
		
		if (suffix != null) {
			logicTargetPath.append(suffix);
		}
		
		String logicTargetStr = logicTargetPath.toString().replaceAll("[/]+", "/");
		String fullTargetPath = saveBaseURL + "/" + logicTargetStr;
		fullTargetPath = fullTargetPath.replaceAll("[/]+", "/");
		fullTargetPath = fullTargetPath.replaceAll("http:/", "http://");
		saveFileToRemoteTool.save(srcFileBytes, fullTargetPath.toString());
		return logicTargetStr;
	}

	/** @Title: saveFile
	 * @Description: TODO
	 * @Author: 崔勇	cysyz1229@gmail.com
	 * @Version: V1.00
	 * @Date 2014-2-17 上午11:28:00
	 * @param srcFileBytes
	 * @param srcFileName
	 * @param saveBaseURL
	 * @param saveDir
	 * @param suffix
	 * @param saveFileToRemoteTool
	 * @return
	 */
	public String saveFile(byte[] srcFileBytes, String srcFileName,
			String saveBaseURL, String saveDir, String suffix,
			ISaveFileToRemoteTool saveFileToRemoteTool) {
		return this.saveFile0(srcFileBytes, srcFileName, saveBaseURL, saveDir, suffix, saveFileToRemoteTool);
	}



}
